package com.ccq.farm.common.config;/**
 * Created by HiWin10 on 2018-06-30.
 */

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.ccq.farm.shiro.ec.EcFormAuthenticationFilter;
import com.ccq.farm.shiro.ec.EcShiroRealm;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.RememberMeManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.SessionValidationScheduler;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.session.mgt.eis.SessionIdGenerator;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author ccq
 * @create 2018-06-30 下午 17:30
 **/
@Configuration
public class ShiroConfig {


    @Bean
    public ShiroFilterFactoryBean shiroFilter(@Qualifier(value = "ecSecurityManager") SecurityManager ecSecurityManager) {
//        System.out.println("ShiroConfiguration.shirFilter()");


        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(ecSecurityManager);


        Map<String, Filter> filters = new LinkedHashMap<>();
        filters.put("authc", ecFormAuthenticationFilter());

        shiroFilterFactoryBean.setFilters(filters);


        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        //注意过滤器配置顺序 不能颠倒
        //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了，登出后跳转配置的loginUrl
        filterChainDefinitionMap.put("/ec/logoutUrl", "logout");
        // 配置不会被拦截的链接 顺序判断
        filterChainDefinitionMap.put("/login.jsp", "authc");
        filterChainDefinitionMap.put("**/druid/**", "anon");
        filterChainDefinitionMap.put("/static/**", "anon");
        filterChainDefinitionMap.put("**/asset/**", "anon");
        filterChainDefinitionMap.put("**/common/**", "anon");
        filterChainDefinitionMap.put("/ec/signUpUrl", "anon");
        filterChainDefinitionMap.put("/ec/**", "anon");
        filterChainDefinitionMap.put("/ec/user/**", "authc");
        filterChainDefinitionMap.put("/ec/loginUrl", "authc");
        filterChainDefinitionMap.put("/**", "user");
        //配置shiro默认登录界面地址，前后端分离中登录界面跳转应由前端路由控制，后台仅返回json数据
        //shiroFilterFactoryBean.setLoginUrl("/ec/toLogin");
        // 登录成功后要跳转的链接
//        shiroFilterFactoryBean.setSuccessUrl("/index");
        //未授权界面;
//        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    @Bean
    public EcFormAuthenticationFilter ecFormAuthenticationFilter() {
        EcFormAuthenticationFilter filter = new EcFormAuthenticationFilter();
        filter.setLoginUrl("/ec/loginUrl");
        filter.setSuccessUrl("/ec/homeUrl");
        filter.setUsernameParam("userName");
        filter.setPasswordParam("userPwd");
        return filter;
    }


    /**
     * securityManager 配置
     *
     * @return
     */
    @Bean(name = "ecSecurityManager")
    public SecurityManager ecSecurityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setCacheManager(ehCacheManager());
        securityManager.setRealm(ecShiroRealm());
        securityManager.setSessionManager(ecSessionManager());
        securityManager.setRememberMeManager(ecRememberMeManager());

        return securityManager;
    }

    @Bean
    public RememberMeManager ecRememberMeManager() {
        CookieRememberMeManager rememberMeManager = new CookieRememberMeManager();
        byte[] decode = Base64.decode("kPH+bIxk5D2deZiIxcaaaA==");
        rememberMeManager.setCipherKey(decode);
        rememberMeManager.setCookie(ecRememberMeCokie());
        return rememberMeManager;
    }

    @Bean
    public Cookie ecRememberMeCokie() {
        SimpleCookie cookie = new SimpleCookie();
        cookie.setName("rememberMe");
        cookie.setMaxAge(604800);
        cookie.setHttpOnly(true);
        return cookie;
    }

    @Bean
    public EhCacheManager ehCacheManager() {
        EhCacheManager cacheManager = new EhCacheManager();
        cacheManager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
        return cacheManager;
    }



    /**
     * 会话管理器
     *
     * @return
     */
    @Bean
    public SessionManager ecSessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setGlobalSessionTimeout(604800000);
        sessionManager.setDeleteInvalidSessions(true);
        sessionManager.setSessionValidationSchedulerEnabled(true);
        sessionManager.setSessionValidationScheduler(ecSessionValidationScheduler());
        sessionManager.setSessionDAO(ecSessionDao());
        sessionManager.setSessionIdCookieEnabled(true);
        sessionManager.setSessionIdCookie(ecSessionIdCookie());
        return sessionManager;
    }

    /**
     * 会话cookie
     *
     * @return
     */
    @Bean
    public Cookie ecSessionIdCookie() {
        SimpleCookie cookie = new SimpleCookie();
        cookie.setName("sid");
        cookie.setMaxAge(-1);
        cookie.setHttpOnly(true);
        return cookie;
    }

    /**
     * 会话dao
     *
     * @return
     */
    @Bean
    public SessionDAO ecSessionDao() {
        EnterpriseCacheSessionDAO sessionDao = new EnterpriseCacheSessionDAO();
        sessionDao.setActiveSessionsCacheName("shiro-activeSessionCache");
        sessionDao.setSessionIdGenerator(ecSessionIdGenerator());
        return sessionDao;
    }

    @Bean
    public SessionIdGenerator ecSessionIdGenerator() {
        JavaUuidSessionIdGenerator sessionIdGenerator = new JavaUuidSessionIdGenerator();

        return sessionIdGenerator;
    }

    @Bean
    public SessionValidationScheduler ecSessionValidationScheduler() {
        ExecutorServiceSessionValidationScheduler scheduler = new ExecutorServiceSessionValidationScheduler();
        scheduler.setInterval(3600000);
        //scheduler.setSessionManager((ValidatingSessionManager) ecSessionManager());
        return scheduler;
    }

    /**
     * ecShiroRealm
     *
     * @return
     */
    @Bean(name = "ecShiroRealm")
    public EcShiroRealm ecShiroRealm() {
        EcShiroRealm ecShiroRealm = new EcShiroRealm();
        return ecShiroRealm;
    }

    @Bean
    public ShiroDialect shiroDialect(){
        return new ShiroDialect();
    }
}
